﻿namespace HostTracker.Azure.Management

open System
open System.Net
open System.ServiceModel
open System.ServiceModel.Web
open System.Runtime.Serialization
open HostTracker.Azure.Management.FSharpExtensions

(*
<?xml version="1.0" encoding="utf-8"?>
  <StorageServices xmlns="http://schemas.microsoft.com/windowsazure">
    <StorageService>
      <Url>storage-account-request-uri</Url>    
      <ServiceName>storage-account-name</ServiceName>  
    </StorageService>  
  </StorageServices>
*)
[<DataContract(Name = "StorageService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageService() =
    let mutable url = ""
    let mutable serviceName = ""
    [<DataMember(Name = "Url", Order = 1)>]
    member x.Url with get() = url and set v = url <- v
    [<DataMember(Name = "ServiceName", Order = 2)>]
    member x.Name with get () = serviceName and set v = serviceName <- v

[<CollectionDataContract(Name = "StorageServices", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServices() = inherit System.Collections.Generic.List<StorageService>()

(*
<?xml version="1.0" encoding="utf-8"?>
  <StorageService xmlns="http://schemas.microsoft.com/windowsazure">
    <Url>storage-account-request-uri</Url>
    <ServiceName>storage-account-name</ServiceName>
    <StorageServiceProperties>
      <Description>description</Description>
      <AffinityGroup>affinity-group</AffinityGroup>
      <Location>location</Location>
      <Label>base64-encoded-label</Label>  
      <Status>status</Status>
    <Endpoints>
      <Endpoint>http://{storage-service-name}.blob.core.windows-int.net/</Endpoint>
      <Endpoint>http://{storage-service-name}.queue.core.windows-int.net/</Endpoint>
      <Endpoint>http://{storage-service-name}.table.core.windows-int.net/</Endpoint>
    </Endpoints>
    </StorageServiceProperties>
  </StorageService>
*)
[<DataContract(Name = "Endpoints", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceEndpoints() =
    let mutable blob = ""
    let mutable queue = ""
    let mutable table = ""
    [<DataMember(Name = "Endpoint", Order = 1)>]
    member x.BlobEndpoint with get() = blob and set v = blob <- v
    [<DataMember(Name = "Endpoint", Order = 2)>]
    member x.QueueEndpoint with get() = queue and set v = queue <- v
    [<DataMember(Name = "Endpoint", Order = 3)>]
    member x.TableEndpoint with get() = table and set v = table <- v

type StorageServiceStatus = Creating | ResolvingDns | Created | Deleting
with
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse str = Reflection.stringToUnionPlain<StorageServiceStatus> str

[<DataContract(Name = "StorageServiceProperties", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceProperties() = 
    let mutable desc = ""
    let mutable affinityGroup = ""
    let mutable loc = ""
    let mutable label = ""
    let mutable status = Created
    let mutable endpoints = StorageServiceEndpoints()
    [<DataMember(Name = "Description", Order = 1)>]
    member x.Description with get() = desc and set v = desc <- v
    [<DataMember(Name = "AffinityGroup", Order = 2, IsRequired = false)>]
    member x.AffinityGroup with get() = affinityGroup and set v = affinityGroup <- v
    [<DataMember(Name = "Location", Order = 3, IsRequired = false)>]
    member x.Location with get() = loc and set v = loc <- v
    [<DataMember(Name = "Label", Order = 4)>]
    member private x.LabelEncoded with get () = label and set v = label <- v
    member x.Label with get() = label.FromBase64() and set (v: string) = label <- v.ToBase64()
    [<DataMember(Name = "Status", Order = 5)>]
    member private x.StatusStr 
        with get() = status.ToString() and 
            set v = status <- StorageServiceStatus.Parse v
    member x.Status = status
    [<DataMember(Name = "Endpoints", Order = 6)>]
    member x.Endpoints with get () = endpoints and set v = endpoints <- v

[<DataContract(Name = "StorageService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceExtended() =
    let mutable url = ""
    let mutable serviceName = ""
    let mutable props = StorageServiceProperties()    
    [<DataMember(Name = "Url", Order = 1)>]
    member x.Url with get() = url and set v = url <- v
    [<DataMember(Name = "ServiceName", Order = 2)>]
    member x.Name with get () = serviceName and set v = serviceName <- v
    [<DataMember(Name = "StorageServiceProperties", Order = 3)>]
    member x.Properties with get () = props and set v = props <- v

(*
<?xml version="1.0" encoding="utf-8"?>
  <StorageService xmlns="http://schemas.microsoft.com/windowsazure">
    <Url>storage-service-url</Url>
    <StorageServiceKeys>
      <Primary>primary-key</Primary>
      <Secondary>secondary-key</Secondary>
    </StorageServiceKeys>
  </StorageService>
*)
[<DataContract(Name = "StorageServiceKeys", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceKeys() =
    let mutable primary = ""
    let mutable secondary =""
    [<DataMember(Name = "Primary", Order = 1)>]
    member x.Primary with get() = primary and set v = primary <- v
    [<DataMember(Name = "Secondary", Order = 2)>]
    member x.Secondary with get() = secondary and set v = secondary <- v

[<DataContract(Name = "StorageService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceWithKeys() =
    let mutable url = ""
    let mutable serviceName = ""
    let mutable keys = StorageServiceKeys()
    [<DataMember(Name = "Url", Order = 1)>]
    member x.Url with get() = url and set v = url <- v
    [<DataMember(Name = "ServiceName", Order = 2)>]
    member x.Name with get () = serviceName and set v = serviceName <- v
    [<DataMember(Name = "StorageServiceKeys", Order = 3)>]
    member x.Keys with get () = keys and set v = keys <- v

(*
<?xml version="1.0" encoding="utf-8"?>
<RegenerateKeys xmlns="http://schemas.microsoft.com/windowsazure">
  <KeyType>Primary|Secondary</KeyType>
</RegenerateKeys>
*)
type KeyType = Primary| Secondary
with
    override x.ToString() = Reflection.unionToStringPlain x
    static member Parse str = Reflection.stringToUnionPlain<KeyType> str

[<DataContract(Name = "RegenerateKeys", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type KeyRegeneration(keyType) =
    [<DataMember(Name = "KeyType", Order = 1)>]
    member private x.KeyType with get () = keyType.ToString() and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
<CreateStorageServiceInput xmlns="http://schemas.microsoft.com/windowsazure">
   <ServiceName>service-name</ServiceName>
   <Description>service-description</Description>
   <Label>base64-encoded-label</Label>
   <AffinityGroup>affinity-group-name</AffinityGroup>
   <Location>location-of-the-storage-account</Location>
</CreateStorageServiceInput>
*)
[<DataContract(Name = "CreateStorageServiceInput", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceCreationWithLocation() =
    let mutable serviceName = ""
    let mutable desc = ""
    let mutable label = ""
    let mutable loc = ""
    [<DataMember(Name = "ServiceName", Order = 1)>]
    member x.Name with get() = serviceName and set v = serviceName <- v
    [<DataMember(Name = "Description", Order = 2)>]
    member x.Description with get() = desc and set v = desc <- v
    [<DataMember(Name = "Label", Order = 3)>]
    member private x.LabelEncoded with get () = label and set v = label <- v
    member x.Label with get() = label.FromBase64() and set (v: string) = label <- v.ToBase64()
    [<DataMember(Name = "Location", Order = 4)>]
    member x.Location with get() = loc and set v = loc <- v

[<DataContract(Name = "CreateStorageServiceInput", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceCreationWithAffinityGroup() =
    let mutable serviceName = ""
    let mutable desc = ""
    let mutable label = ""
    let mutable affinityGroup = ""
    [<DataMember(Name = "ServiceName", Order = 1)>]
    member x.Name with get() = serviceName and set v = serviceName <- v
    [<DataMember(Name = "Description", Order = 2)>]
    member x.Description with get() = desc and set v = desc <- v
    [<DataMember(Name = "Label", Order = 3)>]
    member private x.LabelEncoded with get () = label and set v = label <- v
    member x.Label with get() = label.FromBase64() and set (v: string) = label <- v.ToBase64()
    [<DataMember(Name = "AffinityGroup", Order = 4)>]
    member x.AffinityGroup with get() = affinityGroup and set v = affinityGroup <- v

(*
<?xml version="1.0" encoding="utf-8"?>
<UpdateStorageServiceInput xmlns="http://schemas.microsoft.com/windowsazure">
    <Description>Description of the storage service</Description>
    <Label>base64 encoded label</Label>
</UpdateStorageServiceInput>
*)
[<DataContract(Name = "UpdateStorageServiceInput", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type StorageServiceUpdate() =
    let mutable desc = ""
    let mutable label = ""
    [<DataMember(Name = "Description", Order = 1)>]
    member x.Description with get () = desc and set v = desc <- v
    [<DataMember(Name = "Label", Order = 2)>]
    member private x.LabelEncoded with get () = label and set v = label <- v
    member x.Label with get () = label.FromBase64() and set (v:string) = label <- v.ToBase64()

[<Interface>]
[<ServiceContractAttribute>]
type IStorageManagement =
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices", Method="GET")>]
    abstract ListStorageServices: unit -> StorageServices
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginListStorageServices: callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndListStorageServices: result:IAsyncResult -> StorageServices
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices/{serviceName}", Method="GET")>]
    abstract GetStorageService: serviceName: string -> StorageServiceExtended
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginGetStorageService: serviceName: string *callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndGetStorageService: result:IAsyncResult -> StorageServiceExtended
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices/{serviceName}/keys", Method="GET")>]
    abstract GetStorageServiceKeys: serviceName: string -> StorageServiceWithKeys
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginGetStorageServiceKeys: serviceName: string *callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndGetStorageServiceKeys: result:IAsyncResult -> StorageServiceWithKeys
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices/{serviceName}/keys?action=regenerate", Method="POST")>]
    abstract RegenerateStorageServiceKeys: serviceName: string * keyRegeneration:KeyRegeneration -> StorageServiceWithKeys
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginRegenerateStorageServiceKeys: serviceName: string* keyRegeneration:KeyRegeneration *callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndRegenerateStorageServiceKeys: result:IAsyncResult -> StorageServiceWithKeys
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices", Method="POST")>]
    abstract CreateStorageServiceInLocation: creation: StorageServiceCreationWithLocation -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginCreateStorageServiceInLocation: creation: StorageServiceCreationWithLocation *callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndCreateStorageServiceInLocation: result:IAsyncResult -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices", Method="POST")>]
    abstract CreateStorageServiceWithAffinityGroup: creation: StorageServiceCreationWithAffinityGroup -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginCreateStorageServiceWithAffinityGroup: creation: StorageServiceCreationWithAffinityGroup *callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndCreateStorageServiceWithAffinityGroup: result:IAsyncResult -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices/{serviceName}", Method="DELETE")>]
    abstract DeleteStorageService: serviceName: string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginDeleteStorageService: serviceName: string*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndDeleteStorageService: result:IAsyncResult -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/storageservices/{serviceName}", Method="PUT")>]
    abstract UpdateStorageService: serviceName: string * update: StorageServiceUpdate -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpdateStorageService: serviceName: string* update: StorageServiceUpdate *callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndUpdateStorageService: result:IAsyncResult -> unit